package aclInfoCollector.filesAnalysers.component.fractalFile;

import java.io.File;
import java.io.FilenameFilter;
import java.io.StringReader;
import java.util.ArrayList;

import javax.swing.JLabel;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;

import aclInfoCollector.filesAnalysers.component.ComponentFileAnalyser;

import aclInfoCollector.utils.extensionsFilters.DotFractalFilter;
import aclInfoCollector.utils.specialString.StringInterface;

/**
 * La classe FractalParser permet de parser un fichier fractal
 * 
 * @version 1.0
 *@author Bendavid Olivier
 *@author Haderer Nicolas
 */

public class FractalAnalyser extends ComponentFileAnalyser{
	
	public FractalAnalyser() {
		super();

	}

	
	/**
	 * recherche et parse des fichiers fractal pour retourner une liste de
	 * composants
	 * 
	 * @param directoryPath
	 * @return
	 */

	public void launchAnalysis(String directoryPath) {
		File directoryToScan = new File(directoryPath);
		File[] Files = directoryToScan.listFiles();
		FilenameFilter filter = new DotFractalFilter();
		for (int i = 0; i < Files.length; i++) {
			if (Files[i].isDirectory()) {
				launchAnalysis(Files[i].getAbsolutePath());
			}
		}
		File[] FilesFractal = directoryToScan.listFiles(filter);
		for (int i = 0; i < FilesFractal.length; i++) {
			parseFractalFile(FilesFractal[i]);
		}
	}

	public void parseFractalFile(File f) {

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setIgnoringElementContentWhitespace(true);
		try {
			DocumentBuilder db = dbf.newDocumentBuilder();
			db.setErrorHandler(new ErrorHandlerFractalParser());
			db.setEntityResolver(new EntityResolverFractal());
			document = db.parse(f);
			document.normalize();
		} catch (Exception e) {
		}

		parseDefinitions();
		parseInterfaces();
		parseComponents();

	}

	public void parseFractalFile(String s) {

		File f = new File(s);
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setIgnoringElementContentWhitespace(true);
		try {
			DocumentBuilder db = dbf.newDocumentBuilder();
			db.setErrorHandler(new ErrorHandlerFractalParser());
			db.setEntityResolver(new EntityResolverFractal());
			document = db.parse(f);
			document.normalize();
		} catch (Exception e) {
		}

		parseDefinitions();
		parseInterfaces();
		parseComponents();

	}

	public void parseDefinitions() {
		String compS = "";
		try {
			for (int i = 0; i < document.getElementsByTagName("definition")
					.getLength(); i++) {
				compS = document.getElementsByTagName("definition").item(i)
						.getAttributes().getNamedItem("name").toString();
				compS = compS.substring(compS.indexOf("\"") + 1,
						compS.length() - 1);
				if (!components.contains(compS)) {
					components.add(compS);
				}
				try {
					String superComp = document.getElementsByTagName(
							"definition").item(i).getAttributes().getNamedItem(
							"extends").toString();
					superComp = superComp
							.substring(superComp.indexOf("\"") + 1, superComp
									.length() - 1);
					if (!componentsWithSuperComps.containsKey(compS)) {
						ArrayList<String> a = new ArrayList<String>();
						componentsWithSuperComps.put(compS, a);
						componentsWithSuperComps.get(compS).add(superComp);
					} else {
						if (!componentsWithSuperComps.get(compS).contains(
								superComp)) {
							componentsWithSuperComps.get(compS).add(superComp);
						}
					}
				} catch (Exception e) {
				}

				try {

					for (int h = 0; h < document.getElementsByTagName(
							"definition").item(i).getChildNodes().getLength(); h++) {

						try {
							if (document.getElementsByTagName("definition")
									.item(i).getChildNodes().item(h)
									.getNodeName() == "interface") {
								String inte = document.getElementsByTagName(
										"definition").item(i).getChildNodes()
										.item(h).getAttributes().getNamedItem(
												"signature").toString();

								String role = document.getElementsByTagName(
										"definition").item(i).getChildNodes()
										.item(h).getAttributes().getNamedItem(
												"role").toString();

								String signature = document
										.getElementsByTagName("definition")
										.item(i).getChildNodes().item(h)
										.getAttributes().getNamedItem(
												"signature").toString();

								StringInterface inter = new StringInterface();
								inter.setName(inte.substring(
										inte.indexOf("\"") + 1,
										inte.length() - 1));
								inter.setRole(role.substring(
										role.indexOf("\"") + 1,
										role.length() - 1));
								inter.setSignature(signature.substring(
										signature.indexOf("\"") + 1, signature
												.length() - 1));

								if (!componentsWithInterfaces
										.containsKey(compS)) {
									ArrayList<StringInterface> a = new ArrayList<StringInterface>();
									componentsWithInterfaces.put(compS, a);
									componentsWithInterfaces.get(compS).add(
											inter);
								} else {
									boolean test = true;
									for (StringInterface sit : componentsWithInterfaces
											.get(compS)) {
										if (sit.getName().equals(
												inter.getName())) {
											test = false;
										}
									}
									if (test) {
										componentsWithInterfaces.get(compS)
												.add(inter);
									}
								}

							}
						} catch (Exception e) {
						}

					}
				}

				catch (Exception e) {
				}
			}
		} catch (Exception e) {
		}
	}

	public void parseComponents() {
		String compS = "";
		try {
			for (int i = 0; i < document.getElementsByTagName("component")
					.getLength(); i++) {
				String comp = document.getElementsByTagName("component")
						.item(i).getAttributes().getNamedItem("name")
						.toString();
				comp = comp
						.substring(comp.indexOf("\"") + 1, comp.length() - 1);
				String sig = "";
				try {
					sig = document.getElementsByTagName("component").item(i)
							.getAttributes().getNamedItem("definition")
							.toString();
					sig = sig
							.substring(sig.indexOf("\"") + 1, sig.length() - 1);
				} catch (Exception e) {
				}
				if (sig != "") {
					comp = sig;
				}

				if (comp.startsWith("{$")) {
					if (!componentsWithArgs.contains(comp)) {
						componentsWithArgs.add(comp);
					}
					comp = "";
				}

				if (comp != "") {

					if (!components.contains(comp)) {
						components.add(comp);
					}
					if (!componentsWithInterfaces.containsKey(comp)) {
						ArrayList<StringInterface> a = new ArrayList<StringInterface>();
						componentsWithInterfaces.put(comp, a);
					}
					if (!componentsWithSuperComps.containsKey(comp)) {
						ArrayList<String> a = new ArrayList<String>();
						componentsWithSuperComps.put(comp, a);
						componentsWithSuperComps.get(comp).add(compS);
					} else {
						componentsWithSuperComps.get(comp).add(compS);
					}
					for (int h = 0; h < document.getElementsByTagName(
							"component").item(i).getChildNodes().getLength(); h++) {

						try {
							if (document.getElementsByTagName("component")
									.item(i).getChildNodes().item(h)
									.hasAttributes()) {
								String inte = document.getElementsByTagName(
										"component").item(i).getChildNodes()
										.item(h).getAttributes().getNamedItem(
												"signature").toString();
								String role = document.getElementsByTagName(
										"component").item(i).getChildNodes()
										.item(h).getAttributes().getNamedItem(
												"role").toString();
								String signature = document
										.getElementsByTagName("component")
										.item(i).getChildNodes().item(h)
										.getAttributes().getNamedItem(
												"signature").toString();

								StringInterface inter = new StringInterface();
								inter.setName(inte.substring(
										inte.indexOf("\"") + 1,
										inte.length() - 1));
								inter.setRole(role.substring(
										role.indexOf("\"") + 1,
										role.length() - 1));
								inter.setSignature(signature.substring(
										signature.indexOf("\"") + 1, signature
												.length() - 1));
								boolean test = true;
								for (StringInterface sit : componentsWithInterfaces
										.get(comp)) {
									if (sit.getName().equals(inter.getName())) {
										test = false;
									}
								}
								if (test) {
									componentsWithInterfaces.get(comp).add(
											inter);
								}

							}
						} catch (Exception e) {
						}
					}

				}
			}
		} catch (Exception e) {
			e.toString();
		}
	}

	public void parseInterfaces() {
		try {
			for (int i = 0; i < document.getElementsByTagName("interface")
					.getLength(); i++) {
				String inte = document.getElementsByTagName("interface")
						.item(i).getAttributes().getNamedItem("signature")
						.toString();
				String role = document.getElementsByTagName("interface")
						.item(i).getAttributes().getNamedItem("role")
						.toString();
				String signature = document.getElementsByTagName("interface")
						.item(i).getAttributes().getNamedItem("signature")
						.toString();

				StringInterface inter = new StringInterface();

				inter.setName(inte.substring(inte.indexOf("\"") + 1, inte
						.length() - 1));
				inter.setRole(role.substring(role.indexOf("\"") + 1, role
						.length() - 1));
				inter.setSignature(signature.substring(
						signature.indexOf("\"") + 1, signature.length() - 1));

				boolean test = true;
				for (StringInterface sit : interfaces) {
					if (sit.getName().equals(inter.getName())) {
						test = false;
					}
				}
				if (test) {
					interfaces.add(inter);
				}
			}
		} catch (Exception e) {
			e.toString();
		}

	}

	public void parseFRACTALFile(File f) {

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setIgnoringElementContentWhitespace(true);
		try {
			DocumentBuilder db = dbf.newDocumentBuilder();
			db.setErrorHandler(new ErrorHandlerFractalParser());
			db.setEntityResolver((EntityResolver) new EntityResolverFractal());

			document = db.parse(f);
			document.normalize();
		} catch (Exception e) {
		}

		parseDefinitions();
		parseInterfaces();
		parseComponents();

	}

	public void xmlTextToDocument() {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setIgnoringElementContentWhitespace(true);
		try {
			DocumentBuilder db = dbf.newDocumentBuilder();
			InputSource inStream = new InputSource();
			inStream.setCharacterStream(new StringReader(text));
			document = db.parse(inStream);
			document.normalize();
		} catch (Exception e) {
		}
	}

	public static void main(String[] args) {
		System.out.println("debut");
		FractalAnalyser jf = new FractalAnalyser();

		jf.launchAnalysis("/home/olivier/workACL/acl-infoCollect/dreamALL");
		jf.printSummary();
		System.out.println("fin");

	}


	public void launchAnalysis(String directoryPath, JLabel label) 
	{
		File directoryToScan = new File(directoryPath);
		File[] Files = directoryToScan.listFiles();
		FilenameFilter filter = new DotFractalFilter();
		for (int i = 0; i < Files.length; i++) {
			if (Files[i].isDirectory()) {
				launchAnalysis(Files[i].getAbsolutePath());
			}
		}
		File[] FilesFractal = directoryToScan.listFiles(filter);
		for (int i = 0; i < FilesFractal.length; i++) {
			parseFractalFile(FilesFractal[i], label);
		}
		
	}


	public void parseFractalFile(File f, JLabel label) {
		label.setText(f.getAbsolutePath());
		label.repaint();
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setIgnoringElementContentWhitespace(true);
		try {
			DocumentBuilder db = dbf.newDocumentBuilder();
			db.setErrorHandler(new ErrorHandlerFractalParser());
			db.setEntityResolver(new EntityResolverFractal());
			document = db.parse(f);
			document.normalize();
		} catch (Exception e) {
		}

		parseDefinitions();
		parseInterfaces();
		parseComponents();
	}

	
}
